﻿using CommonModel.Field;
using CommonModel.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using static CommonModel.Model.DataTypeDll;

namespace CommonModel.Util
{
    public class Struct
    {
        //解决字典不能添加重复键值，loop时用
        public class RepeatDictionaryComparer : IEqualityComparer<string>
        {
            public bool Equals(string x, string y)
            {
                return x != y;
            }
            public int GetHashCode(string obj)
            {
                return obj.GetHashCode();
            }
        }


        //结构体解析
        public static Dictionary<string, Object> ByteParseViaStruct(SchemaDocument doc, byte[] data,int bodybegin)
        {

            int currentCursor = bodybegin; // data字节数组解析游标起始位置
            int currentParsedIndex = 0; // 解析后字段的顺序
            Dictionary<int, Object> schemaDictionary = doc.getFieldDictionary();//读取的XML模板的字段字典
            Dictionary<string, Object> parsedDataDictionary = new Dictionary<string, object>();//解析后的字典
            parseDictionary(schemaDictionary, parsedDataDictionary, data, ref currentCursor, ref currentParsedIndex);
            return parsedDataDictionary;
        }

        //解析函数

        public static void parseDictionary(Dictionary<int, Object> schemaDictionary, Dictionary<string, Object> parsedDataDictionary, byte[] data, ref int currentCursor, ref int currentParsedIndex)
        {

            for (int i = 0; i < schemaDictionary.Count; i++) 
            {
                Object schObj = schemaDictionary[i];

                //如果是普通字段，且字节位标识bit字段
                if (schObj is FieldSchema)
                {
                    FieldSchema schField = (FieldSchema)schObj;
                    FieldData parField = new ParsedField();
                    string pname = schField.getName();//当前解析到的字段的名字            
                    parField.setName(pname);

                    //如果需要告警
                    if (schField.isAlarm())
                    {
                        parField.setAlarm(true);
                        parField.setAlarmName(schField.getAlarmName());
                        parField.setAlarmValue(schField.getAlarmValue());
                    }
                    DataType type = schField.getType();
                    int size = schField.getSize();
                    try
                    {
                        byte[] datax = new byte[size];
                        //使用字段的长度作为待解析的数据
                        Array.Copy(data, currentCursor, datax, 0, size);//将data字节数组所需解析的当前字段复制过来
                        currentCursor = currentCursor + size;//字节数组游标移动
                        currentParsedIndex++;//移动游标
                        string value = BytesParseToTypeString.ParseValue(type, datax);// 开始解析
                        parField.setValue(value);
                        parField.setType(type);
                        //parsedDataDictionary.Add(schName, parField);//将解析好的字段添加到字段中
                        parsedDataDictionary.Add(pname, value);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Struct.parseDictionary函数解析字段 " + i + " 名称: " + pname + " type: " + type + " 失败!\n" + e);
                    }
                }

                //如果是字段集
                if (schObj is SchemaDictionary)
                {
                    SchemaDictionary subSchDictionary = (SchemaDictionary)schObj;
                    DataType datype = subSchDictionary.getType();
                    string pname = subSchDictionary.getName();
                    int looper = 0;
                    parsedDataDictionary.Add(pname, new List<Dictionary<string, Object>>());
                    switch (datype)
                    {
                        //位状态结构体, 低位在前高位在后
                        case DataType.BITARRAY:
                            looper = getLooper(subSchDictionary, parsedDataDictionary);//获取到循环次数
                            for (int counter = 0; counter < looper; counter++)
                            {
                                ((List<Dictionary<string, Object>>)parsedDataDictionary[pname]).Add(new Dictionary<string, object>());
                                parseBitArray(subSchDictionary
                                    , ((List<Dictionary<string, Object>>)(parsedDataDictionary)[pname])[counter]
                                    , data, ref currentCursor, ref currentParsedIndex);//解析好的子集
                            }
                            break;

                        //结构体类型
                        case DataType.STRUCT:
                            looper = getLooper(subSchDictionary, parsedDataDictionary);//获取到循环次数
                            if (looper == -1)//不解析，进行下一个字段解析
                            {
                                break;
                            }
                            Dictionary<int, Object> subSchFieldDictionary = subSchDictionary.getFieldDictionary();

                            //嵌套循环解析
                            for (int counter = 0; counter < looper; counter++)
                            {
                                ((List<Dictionary<string, Object>>)(parsedDataDictionary)[pname]).Add(new Dictionary<string, object>());
                                parseDictionary(subSchFieldDictionary
                                    , ((List<Dictionary<string, Object>>)(parsedDataDictionary)[pname])[counter]
                                    , data, ref currentCursor, ref currentParsedIndex);//把list传入，有loop的字段放list中存放
                            }

                            break;
                        default:
                            break;
                    }
                }
            }
        }

        /**
         * 获取结构体数组的长度 
         * @param subSchDictionary - 结构体解析字典
         * parsedDataDictionary  解析好的字典
         * @return - 字典中实际的loop属性值, 即数组个数
         */
        public static int getLooper(SchemaDictionary subSchDictionary, Dictionary<string, Object> parsedDataDictionary)
        {
            string loopStr = subSchDictionary.getLoop();
            if (loopStr == "0")
            {
                return -1;//表示不解析该字段
            }
            string loopValueStr = "";
            int loop = 1;

            if (null == loopStr || loopStr.Equals(""))
            {
                loopStr = "1";
            }
            //正则判断是否是数字
            string regex = "^(-?[0-9]*[.]*[0-9]{0,3})$";
            /**
             * 如果是关联字段获取数组个数
             */
            if (Regex.IsMatch(loopStr, regex))
            {
                loopValueStr = loopStr;
                loop = Convert.ToInt32(loopValueStr);  
            }
            else
            {
                // 从已经解析的parsedDataDictionary中取出对应的值
                loopValueStr = parsedDataDictionary[loopStr].ToString();
                loop = Convert.ToInt32(loopValueStr);
            }
/*            // 正则表达式判断数字
            string digitRegex = "\\d+";
            if (Regex.IsMatch(loopStr, digitRegex))
            {
                try
                {
                    loop = Convert.ToInt32(loopValueStr);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
            else
            {
                Console.WriteLine("解析失败");
            }*/

            return loop;
        }

        //解析成字节位结构体
        public static void parseBitArray(SchemaDictionary subSchDictionary, Dictionary<string, Object> parsedDataDictionary, byte[] data, ref int currentCursor, ref int currentParsedIndex)
        {
            int dataSize = subSchDictionary.getSize();
            string name = subSchDictionary.getName();

            //使用字段的长度作为待解析的数据<br/>
            byte[] datax = new byte[dataSize];
            //使用字段的长度作为待解析的数据
            Array.Copy(data, currentCursor, datax, 0, dataSize);//将data字节数组所需解析的当前字段复制过来
            currentCursor = currentCursor + dataSize; // 游标前移该字段的字节长度
            currentParsedIndex++;//移动已解析的数据游标
            Dictionary<string, Object> subParseDictionary = parseBitArrayMap(subSchDictionary, datax);//开始解析子字段集,subParseDictionary是解析好的子字段集      
            parsedDataDictionary.Add(name, subParseDictionary);

        }

        //解析子字段集
        public static Dictionary<string, Object> parseBitArrayMap(SchemaDictionary subSchDictionary, byte[] data)
        {
            //byte数组转换为一个长度为8*N的byte数组
            byte[] bitArray = TransForm.bytesToBitArray(data);


            Dictionary<int, Object> schFieldDictionary = subSchDictionary.getFieldDictionary();
            Dictionary<string, Object> parsedDataDictionary_child = new Dictionary<string, Object>();
            for (int i = 0; i < schFieldDictionary.ToArray().Length; i++)
            {
                FieldSchema fieldSch = (FieldSchema)schFieldDictionary[i];
                DataType typechild = fieldSch.getType();
                if (i < bitArray.Length)
                {
                    FieldData parField = new ParsedField();
                    parField.setName(fieldSch.getName());

                    //如果需要告警
                    if (fieldSch.isAlarm())
                    {
                        parField.setAlarm(true);
                        parField.setAlarmName(fieldSch.getAlarmName());
                        parField.setAlarmValue(fieldSch.getAlarmValue());
                    }

                    byte[] datax = new byte[1];
                    datax[0] = bitArray[i];
                    string value = "";
                    try
                    {
                        value = BytesParseToTypeString.ParseValue(typechild, datax);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                    parField.setValue(value);
                    //parsedDataDictionary_child.Add(fieldSch.getName(), parField);
                    parsedDataDictionary_child.Add(fieldSch.getName(), value);//只要值不要对象
                }
            }
            return parsedDataDictionary_child;
        }
    }
}
